package com.myk.game.gobangchess.rooms;

import com.myk.game.gobangchess.Room;
import com.myk.game.gobangchess.Sign;
import com.myk.game.gobangchess.constants.ColorCost;
import com.myk.game.gobangchess.constants.WinMode;
import com.myk.game.gobangchess.rooms.absrooms.movechess.MoreColorCost;
import com.myk.game.gobangchess.rooms.absrooms.movechess.MovedChess;
import com.myk.game.gobangchess.rooms.absrooms.movechess.MovedChessRoom;
import com.myk.game.gobangchess.signs.*;
import com.myk.game.gobangchess.utils.GridsUtils;
import com.myk.game.gobangchess.utils.Pair;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;

/**
 * 斗兽棋
 */
public class FightingAnimalsRoom extends Room implements MovedChessRoom {

    private CacheSign cacheSign;
    private List<Integer> riverIndexList; //河道格子索引
    private List<Integer> trapIndexList; //陷阱格子索引
    private List<Integer> blackTrapIndexList; //黑方陷阱格子索引
    private List<Integer> whiteTrapIndexList; //白方陷阱格子索引
    private List<Integer> caveIndexList; //兽穴格子索引
    private int blackCaveIndex; //黑方兽穴格子索引
    private int whiteCaveIndex; //白方兽穴格子索引
    private List<Integer> birthIndexList; //出生地索引
    private final List<MovedChess> chessList = new ArrayList<>();
    private final List<int[]> moveArrayList = new ArrayList<>(2); // 走子标记
    private MovedChess selectedChess;

    public FightingAnimalsRoom(String roomName) {
        super(roomName, "传统新棋斗兽棋。", "斗兽棋", GridsUtils.createEmptyGrids(7, 9), true, true);
        initChessboard();
        initBackground();
        initChess();
    }

    private void initChessboard() {
        riverIndexList = new ArrayList<>();
        riverIndexList.add(getIndex(1,3));
        riverIndexList.add(getIndex(1,4));
        riverIndexList.add(getIndex(1,5));
        riverIndexList.add(getIndex(2,3));
        riverIndexList.add(getIndex(2,4));
        riverIndexList.add(getIndex(2,5));
        riverIndexList.add(getIndex(4,3));
        riverIndexList.add(getIndex(4,4));
        riverIndexList.add(getIndex(4,5));
        riverIndexList.add(getIndex(5,3));
        riverIndexList.add(getIndex(5,4));
        riverIndexList.add(getIndex(5,5));
        trapIndexList = new ArrayList<>();
        blackTrapIndexList = new ArrayList<>();
        blackTrapIndexList.add(getIndex(2, 0));
        blackTrapIndexList.add(getIndex(3, 1));
        blackTrapIndexList.add(getIndex(4, 0));
        trapIndexList.addAll(blackTrapIndexList);
        whiteTrapIndexList = new ArrayList<>();
        whiteTrapIndexList.add(getIndex(2, 8));
        whiteTrapIndexList.add(getIndex(3, 7));
        whiteTrapIndexList.add(getIndex(4, 8));
        trapIndexList.addAll(whiteTrapIndexList);
        caveIndexList = new ArrayList<>();
        caveIndexList.add(blackCaveIndex = getIndex(3, 0));
        caveIndexList.add(whiteCaveIndex = getIndex(3, 8));
        birthIndexList = new ArrayList<>();
        birthIndexList.add(getIndex(0, 0));
        birthIndexList.add(getIndex(0, 2));
        birthIndexList.add(getIndex(1, 1));
        birthIndexList.add(getIndex(2, 2));
        birthIndexList.add(getIndex(4, 2));
        birthIndexList.add(getIndex(5, 1));
        birthIndexList.add(getIndex(6, 0));
        birthIndexList.add(getIndex(6, 2));
        birthIndexList.add(getIndex(0, 8));
        birthIndexList.add(getIndex(0, 6));
        birthIndexList.add(getIndex(1, 7));
        birthIndexList.add(getIndex(2, 6));
        birthIndexList.add(getIndex(4, 6));
        birthIndexList.add(getIndex(5, 7));
        birthIndexList.add(getIndex(6, 8));
        birthIndexList.add(getIndex(6, 6));

    }

    private void initBackground() {
        String bgColor = "#FF26836F";
        String gridColor = "#FFADD1D6";
        String riverColor = "#FF77B2FE";
        String birthColor = "#FFDBDF9E";
        List<Sign> chessboardStyle = new ArrayList<>();
        List<Integer> indexList = new ArrayList<>();
        int maxRow = curGrids.length - 1;
        int maxCol = curGrids[0].length - 1;
        for (int i = 0; i < 7; i++) {
            for (int j = 0; j < 9; j++) {
                indexList.add(getIndex(i, j));
            }
        }
        //背景
        chessboardStyle.add(new GroundSign(getIndex(0, 0), getIndex(maxRow, maxCol), ColorCost.TABLECLOTH_COLOR, ColorCost.TABLECLOTH_COLOR, 3f, 0, 0));
        chessboardStyle.add(new AroundSign(indexList, bgColor, bgColor, 3f));
        //格子
        for (Integer index : indexList) { //公共
            chessboardStyle.add(new AroundSign(index, gridColor, gridColor, 1f));
        }
        for (Integer index : birthIndexList) { //出生点
            chessboardStyle.add(new AroundSign(index, birthColor, birthColor, 1f));
        }
        //分割线
        for (int i = 1; i <= maxRow; i++) {
            List<Pair<Integer, Integer>> nodes1 = new ArrayList<>();
            nodes1.add(new Pair<>(getIndex(i, 0), 0)); //起点
            nodes1.add(new Pair<>(getIndex(i, maxCol), 2)); //终点
            chessboardStyle.add(new PathSign(nodes1, bgColor, bgColor, 1f, 0));
        }
        for (int j = 1; j <= maxCol; j++) {
            List<Pair<Integer, Integer>> nodes1 = new ArrayList<>();
            nodes1.add(new Pair<>(getIndex(0, j), 0)); //起点
            nodes1.add(new Pair<>(getIndex(maxRow, j), 6)); //终点
            chessboardStyle.add(new PathSign(nodes1, bgColor, bgColor, 1f, 0));
        }
        //河道
        chessboardStyle.add(new AroundSign(riverIndexList, riverColor, riverColor, 1f));
        chessboardStyle.add(new AroundSign(riverIndexList, ColorCost.TRANSPARENT, bgColor, 1f));
        chessboardStyle.add(new TitleSign(0.5f,0.26f,0,"🐸","#33FFFFFF",1.3f));
        chessboardStyle.add(new TitleSign(0.5f,0.682f,0,"🐸","#33FFFFFF",1.3f));
        //陷阱
        for (Integer trapIndex : trapIndexList) {
            chessboardStyle.add(new TextSign(trapIndex, "🕳", ColorCost.BLACK)); //🕳🕸
        }
        //兽穴
        for (Integer caveIndex : caveIndexList) {
            chessboardStyle.add(new TextSign(caveIndex, "🏕", ColorCost.BLACK)); //🏕
        }
        //添加到缓存标记
        cacheSign = new CacheSign(this, "background", 33, true, chessboardStyle); //*** 修改背景样式记得改这里的版本号！！！
    }

    private void initChess() {
        chessList.clear();
        chessList.add(new Tiger(1, 0, 0));
        chessList.add(new Elephant(1, 0, 2));
        chessList.add(new Cat(1, 1, 1));
        chessList.add(new Wolf(1, 2, 2));
        chessList.add(new Leopard(1, 4, 2));
        chessList.add(new Dog(1, 5, 1));
        chessList.add(new Lion(1, 6, 0));
        chessList.add(new Mouse(1, 6, 2));

        chessList.add(new Mouse(2, 0, 6));
        chessList.add(new Lion(2, 0, 8));
        chessList.add(new Dog(2, 1, 7));
        chessList.add(new Leopard(2, 2, 6));
        chessList.add(new Wolf(2, 4, 6));
        chessList.add(new Cat(2, 5, 7));
        chessList.add(new Elephant(2, 6, 6));
        chessList.add(new Tiger(2, 6, 8));
    }

    @Override
    public String getRuleText() {
        return "{{斗兽棋·游戏说明@scale=1.5}}\n" +
                "{{基本规则:@color=#FFFF3300}}\n" +
                "较大的可吃较小的,同类可以互吃,而鼠则可吃象。动物走一格,前后左右都可以走。\n" +
                "{{陷阱、兽穴:@color=#FFFF3300}}\n" +
                "双方各有三个陷阱和一个兽穴,如果一方进入了对方的兽穴便胜出。任何一方都不能进入自己的兽穴。\n" +
                "如果对方的兽类走进陷阱,已方任何一只兽都可以把它吃掉;如果敌兽进入陷阱,一回会后自己的兽类不吃掉陷阱中的敌兽,当对方进入已方兽穴时,则本方输。\n" +
                "{{小河:@color=#FFFF3300}}\n" +
                "棋盘中间有两条小河,狮、虎可以直接跳过河,而且可以直接把对岸的动物吃掉。只有鼠可以下水,在水中的鼠可以阻隔对方的狮、虎跳河，不会阻隔自己的狮、虎跳河。两鼠在水内可以互吃。水里的动物不可以直接吃陆上的,陆上的动物也不可以直接吃水里的。\n" +
                "{{等级大小:@color=#FFFF3300}}\n" +
                "普通吃法:\n" +
                "象 > 狮 > 虎 > 豹 > 狗 > 狼 > 猫 > 鼠\n" +
                "特殊吃法:\n" +
                "1、鼠吃象法:八兽的吃法除按照大小次序外,惟鼠能吃象。\n" +
                "2、陷阱:棋盘设陷阱,专为限制敌兽的战斗力(自己的兽,不受限制)\n" +
                "3、互吃法:凡是同类相遇,可互相吃,行走一方的动物保留,对方的动物被吃掉。\n" +
                "敌兽走入陷阱,即失去战斗力,本方的任意兽类都可以吃进入陷阱里的兽类。每方在兽穴旁设三个陷阱。\n" +
                "{{胜负:@color=#FFFF3300}}\n" +
                "无论任何一方的兽走入敌方的兽穴就算胜利(自己的兽类不可以走入自己的兽六)\n" +
                "任何一方的动物被吃光了就算失败。";
    }

    @Override
    public CacheSign getCacheSignByName(String cacheName) {
        return cacheSign;
    }

    @Override
    public String getCoordMode() {
        return "00000000";
    }

    @Override
    public String getGameInfo() {
        //先清空棋盘
        curGrids = GridsUtils.copyGrids(originGrids);
        signList.clear();
        signList.add(cacheSign);
        this.render();
        //画一下箭头
        /*for (int[] moveArray : moveArrayList) {
            signList.add(new LineSign(moveArray[0], moveArray[1], ColorCost.MOVE_ARROW_LIGHT, 1));
        }*/
        //画选中效果
        if (selectedChess != null){
            //画一下选中框
            getSignList().add(new AroundSign(getIndex(selectedChess.getRow(), selectedChess.getCol()),  MoreColorCost.MOVE, MoreColorCost.MOVE, 1f));

            //画一下可移动范围
            for (Integer index : selectedChess.getMoveRange(this)) {
                getSignList().add(new TextSign(index,"🐾","#FFFFFFFF"));
            }
            //画一下吃子范围
            for (Integer index : selectedChess.getEatRange(this)) {
                getSignList().add(new TextSign(index,"👄","#BBFFFFFF"));
            }
        }
        return super.getGameInfo();
    }

    @Override
    public void resetGrids() {
        super.resetGrids();
        selectedChess = null;
        moveArrayList.clear();
        initChess();
    }


    @Override
    public void doRule(int row, int col, int value) {
        if (selectOrMove(row, col, value)) {
            stepAdd();
            // 判断下一手是否无棋可走
            boolean isNextCanMove = false;
            // 判断是否走入了对方的兽穴
            boolean isInCave = false;
            // 统计对方剩余棋子数量
            int countChess = 0;
            for (MovedChess chess : chessList) {
                if (chess.getSide() != value){
                    countChess++;
                }
                if (isChessInCave(chess)) {
                    isInCave = true;
                }
                if (isNextCanMove(chess,value)) {
                    isNextCanMove = true;
                }
            }
            //判断是否进入兽穴
            if (isInCave) {
                if (cur == 1) {
                    doOver(WinMode.BLACK_WIN, "黑方进入白方兽穴获胜");
                }
                else {
                    doOver(WinMode.WHITE_WIN, "白方进入黑方兽穴获胜");
                }
                return;
            }
            //判断是否吃光动物
            if (countChess == 0) {
                if (cur == 1) {
                    doOver(WinMode.BLACK_WIN, "黑方吃光白方动物获胜");
                }
                else {
                    doOver(WinMode.WHITE_WIN, "白方吃光黑方动物获胜");
                }
                return;
            }
            //切换行动方
            if (!isNextCanMove) { //对方无法行走我方继续行走
                if (value == 1) {
                    noticeBlackMove();
                }
                else {
                    noticeWhiteMove();
                }
            }
            else { //正常换对方行走
                if (value == 1) {
                    noticeWhiteMove();
                }
                else {
                    noticeBlackMove();
                }
            }
        }
        else {
            noticeAllRefreshGameInfo();//通知界面刷新
        }
    }


    /**
     * 选择或走子
     *
     * @param row 点击位置的row
     * @param col 点击位置的col
     * @return 是否走子成功
     */
    private boolean selectOrMove(int row, int col, int value) {
        MovedChess target = getChessByPos(row, col);
        if (target == null && selectedChess == null) {
            // 既没有点击棋子，又没有已选中的棋子
            return false;
        }
        if (selectedChess == null) {
            if (target.getSide() != value) {
                return false;
            }
            selectedChess = target;
            return false;
        }
        if (selectedChess == target) {
            // 取消选中棋子
            selectedChess = null;
            noticeAllRefreshGameInfo();
            return false;
        }
        if (selectedChess.getSide() != cur) {
            // 选中的是对方的棋子，仅能查看，不能移动
            // 取消选中棋子
            selectedChess = null;
            noticeAllRefreshGameInfo();
            return false;
        }
        // 尝试走子
        int startIndex = getIndex(selectedChess.getRow(), selectedChess.getCol());
        int endIndex = getIndex(row, col);
        if (selectedChess.getMoveRange(this).contains(endIndex)) {
            selectedChess.moveTo(row, col);
            moveArrayList.clear();
            moveArrayList.add(new int[]{startIndex, endIndex});
            selectedChess = null;
            return true;
        }
        else if (selectedChess.getEatRange(this).contains(endIndex)) {
            chessList.remove(getChessByPos(row, col));
            selectedChess.moveTo(row, col);
            moveArrayList.clear();
            moveArrayList.add(new int[]{startIndex, endIndex});
            selectedChess = null;
            return true;
        }
        else {
            selectedChess = null;
            return false;
        }
    }

    //对方棋子的话判断是否能够移动或吃子
    private boolean isNextCanMove(MovedChess chess, int value) {
        return chess.getSide() == getNextCur(value) && (!chess.getMoveRange(this).isEmpty() || !chess.getEatRange(this).isEmpty());
    }

    //判断棋子是否进入对方兽穴
    private boolean isChessInCave(MovedChess chess) {
        if (chess.getSide() == 1){
            return getIndex(chess.getRow(),chess.getCol()) == whiteCaveIndex;
        }
        else {
            return getIndex(chess.getRow(),chess.getCol()) == blackCaveIndex;
        }
    }

    //获取下个行动方
    private int getNextCur(int value) {
        return 3 - value;
    }

    @Override
    public List<MovedChess> getChessList() {
        return chessList;
    }

    @Override
    public MovedChess getSelectedChess() {
        return selectedChess;
    }

    @Override
    public int[][] getCurGrids() {
        return curGrids;
    }

    @Override
    public List<Sign> getSignList() {
        return signList;
    }

    @Override
    public MovedChess getChessByPos(int row, int col) {
        for (MovedChess chess : chessList) {
            if (chess.getRow() == row && chess.getCol() == col) {
                return chess;
            }
        }
        return null;
    }

    @Override
    public MovedChess getChessByIndex(int index) {
        for (MovedChess chess : chessList) {
            if (chess.getIndex(this) == index) {
                return chess;
            }
        }
        return null;
    }

    /**
     * 棋子抽象基类
     */
    public static abstract class Chess implements MovedChess {
        public int row;
        public int col;
        private final int side;
        private final String name;
        private final int level;

        public Chess(String name, int level,int side, int row, int col) {
            this.name = name;
            this.side = side;
            this.row = row;
            this.col = col;
            this.level = level;
        }

        @Override
        public String getColor() {
            return getSide() == 1 ? MoreColorCost.RED_CHESS_WORD : MoreColorCost.WHITE_CHESS_WORD;
        }

        @Override
        public int getRow() {
            return row;
        }

        @Override
        public int getCol() {
            return col;
        }

        @Override
        public void moveTo(int row, int col) {
            this.row = row;
            this.col = col;
        }

        @Override
        public int getSide() {
            return side;
        }

        public int getLevel() {
            return level;
        }

        @Override
        public String getName() {
            return name;
        }


        /**
         * 是否己方兽穴
         */
        public boolean isSelfCave(FightingAnimalsRoom room, Integer integer) {
            if (getSide() == 1 && integer == room.blackCaveIndex) return true;
            return getSide() == 2 && integer == room.whiteCaveIndex;
        }

        /**
         * 是否己方陷阱
         */
        public boolean isSelfTrap(FightingAnimalsRoom room, Integer integer) {
            if (getSide() == 1 && room.blackTrapIndexList.contains(integer)) return true;
            return getSide() == 2 && room.whiteTrapIndexList.contains(integer);
        }

        //将河对岸的格子添加到范围
        public void addRiverBankInRange(MovedChessRoom room, List<Integer> range, boolean isEat) {
            int[][] curGrids = room.getCurGrids();
            int otherSide = 3 - getSide();
            int tRow;
            int[] colArr;
            int tCol;
            int[] rowArr;
            //左跳右
            tCol = 2;
            rowArr = new int[]{1,2,4,5};
            for (int i : rowArr) {
                if (row == i && col == tCol){
                    if (curGrids[i][3] != otherSide && curGrids[i][4] != otherSide && curGrids[i][5] != otherSide){ //中间没有其它棋子阻隔
                        if (isEat){
                            if (curGrids[i][6] == otherSide){//对面有对方棋子时
                                range.add(room.getIndex(i, 6));
                            }
                        }
                        else {
                            if (curGrids[i][6] == 0){
                                range.add(room.getIndex(i, 6));
                            }
                        }
                    }
                }
            }
            //右跳左
            tCol = 6;
            rowArr = new int[]{1,2,4,5};
            for (int i : rowArr) {
                if (row == i && col == tCol){
                    if (curGrids[i][3] != otherSide && curGrids[i][4] != otherSide && curGrids[i][5] != otherSide){ //中间没有其它棋子阻隔
                        if (isEat){
                            if (curGrids[i][2] == otherSide){//对面有对方棋子时
                                range.add(room.getIndex(i, 2));
                            }
                        }
                        else {
                            if (curGrids[i][2] == 0){
                                range.add(room.getIndex(i, 2));
                            }
                        }
                    }
                }
            }
            //上跳中
            tRow = 0;
            colArr = new int[]{3,4,5};
            for (int i : colArr) {
                if (row == tRow && col == i){
                    if (curGrids[1][i] != otherSide && curGrids[2][i] != otherSide){ //中间没有其它棋子阻隔
                        if (isEat){
                            if (curGrids[3][i] == otherSide){//对面有对方棋子时
                                range.add(room.getIndex(3, i));
                            }
                        }
                        else {
                            if (curGrids[3][i] == 0){
                                range.add(room.getIndex(3, i));
                            }
                        }
                    }
                }
            }
            //中跳上下
            tRow = 3;
            colArr = new int[]{3,4,5};
            for (int i : colArr) {
                if (row == tRow && col == i){
                    if (curGrids[1][i] != otherSide && curGrids[2][i] != otherSide){ //中间没有其它棋子阻隔
                        if (isEat){
                            if (curGrids[0][i] == otherSide){//对面有对方棋子时
                                range.add(room.getIndex(0, i));
                            }
                        }
                        else {
                            if (curGrids[0][i] == 0){
                                range.add(room.getIndex(0, i));
                            }
                        }
                    }
                    if (curGrids[5][i] != otherSide && curGrids[4][i]!= otherSide){ //中间没有其它棋子阻隔
                        if (isEat){
                            if (curGrids[6][i] == otherSide){//对面有对方棋子时
                                range.add(room.getIndex(6, i));
                            }
                        }
                        else {
                            if (curGrids[6][i] == 0){
                                range.add(room.getIndex(6, i));
                            }
                        }
                    }
                }
            }
            //下跳中
            tRow = 6;
            colArr = new int[]{3,4,5};
            for (int i : colArr) {
                if (row == tRow && col == i){
                    if (curGrids[5][i] != otherSide && curGrids[4][i] != otherSide){ //中间没有其它棋子阻隔
                        if (isEat){
                            if (curGrids[3][i] == (3-getSide())){//对面有对方棋子时
                                range.add(room.getIndex(3, i));
                            }
                        }
                        else {
                            if (curGrids[3][i] == 0){
                                range.add(room.getIndex(3, i));
                            }
                        }
                    }
                }
            }
        }

        @Override
        public void render(MovedChessRoom room, boolean selected) {
            room.getCurGrids()[getRow()][getCol()] = getSide(); //显示棋子的底座
            room.getSignList().add(new TextSign(room.getIndex(getRow(), getCol()), getName(), getColor()));

        }

    }

    /**
     * 大象
     */
    private static class Elephant extends Chess {
        public Elephant(int mSide, int pRow, int pCol) {
            super("象",8, mSide, pRow, pCol);
        }

        @Override
        public String getName() {
            return "🐘";
        }

        @Override
        public List<Integer> getMoveRange(MovedChessRoom room) {
            List<Integer> range = genMoveRange(room, new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}}, 1);
            //不能走入自家兽穴
            range.removeIf(integer -> isSelfCave((FightingAnimalsRoom) room, integer));
            //不能入河
            range.removeAll(((FightingAnimalsRoom)room).riverIndexList);
            return range;
        }

        @Override
        public List<Integer> getEatRange(MovedChessRoom room) {
            List<Integer> range = genEatRange(room, new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}}, 1);
            //不能入河
            range.removeAll(((FightingAnimalsRoom)room).riverIndexList);
            //不能吃level大于自己的（不能吃老鼠），除非被困住
            List<Integer> removeList = new ArrayList<>();
            for (Integer ran : range) {
                Chess chess = (Chess) room.getChessByIndex(ran);
                if ((chess.level > getLevel() || chess instanceof Mouse) && !isSelfTrap((FightingAnimalsRoom)room,ran)){ //等级大于自己且没有被己方陷阱困住时移除
                    removeList.add(ran);
                }
            }
            range.removeAll(removeList);
            return range;
        }
    }

    /**
     * 狮子
     */
    private static class Lion extends Chess {
        public Lion(int mSide, int pRow, int pCol) {
            super("狮",7, mSide, pRow, pCol);
        }

        @Override
        public String getName() {
            return "🦁";
        }

        @Override
        public List<Integer> getMoveRange(MovedChessRoom room) {
            List<Integer> range = genMoveRange(room, new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}}, 1);
            //不能走入自家兽穴
            range.removeIf(integer -> isSelfCave((FightingAnimalsRoom) room, integer));
            //不能入河
            range.removeAll(((FightingAnimalsRoom)room).riverIndexList);
            //没有老鼠阻挡就能越过河
            addRiverBankInRange(room ,range, false);
            return range;
        }

        @Override
        public List<Integer> getEatRange(MovedChessRoom room) {
            List<Integer> range = genEatRange(room, new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}}, 1);
            //不能入河
            range.removeAll(((FightingAnimalsRoom)room).riverIndexList);
            //没有老鼠阻挡就能越过河
            addRiverBankInRange(room ,range, true);
            //不能吃level大于自己的，除非被困住
            List<Integer> removeList = new ArrayList<>();
            for (Integer ran : range) {
                Chess chess = (Chess) room.getChessByIndex(ran);
                if (chess.level > getLevel() && !isSelfTrap((FightingAnimalsRoom)room,ran)){ //等级大于自己且没有被己方陷阱困住时移除
                    removeList.add(ran);
                }
            }
            range.removeAll(removeList);
            return range;
        }
    }

    /**
     * 老虎
     */
    private static class Tiger extends Chess {
        public Tiger(int mSide, int pRow, int pCol) {
            super("虎",6, mSide, pRow, pCol);
        }

        @Override
        public String getName() {
            return "🐯";
        }

        @Override
        public List<Integer> getMoveRange(MovedChessRoom room) {
            List<Integer> range = genMoveRange(room, new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}}, 1);
            //不能走入自家兽穴
            range.removeIf(integer -> isSelfCave((FightingAnimalsRoom) room, integer));
            //不能入河
            range.removeAll(((FightingAnimalsRoom)room).riverIndexList);
            //没有老鼠阻挡就能越过河
            addRiverBankInRange(room ,range, false);
            return range;
        }

        @Override
        public List<Integer> getEatRange(MovedChessRoom room) {
            List<Integer> range = genEatRange(room, new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}}, 1);
            //不能入河
            range.removeAll(((FightingAnimalsRoom)room).riverIndexList);
            //没有老鼠阻挡就能越过河
            addRiverBankInRange(room ,range, true);
            //不能吃level大于自己的，除非被困住
            List<Integer> removeList = new ArrayList<>();
            for (Integer ran : range) {
                Chess chess = (Chess) room.getChessByIndex(ran);
                if (chess.level > getLevel() && !isSelfTrap((FightingAnimalsRoom)room,ran)){ //等级大于自己且没有被己方陷阱困住时移除
                    removeList.add(ran);
                }
            }
            range.removeAll(removeList);
            return range;
        }

    }

    /**
     * 豹子
     */
    private static class Leopard extends Chess {
        public Leopard(int mSide, int pRow, int pCol) {
            super("豹",5, mSide, pRow, pCol);
        }

        @Override
        public String getName() {
            return "🐆";
        }

        @Override
        public List<Integer> getMoveRange(MovedChessRoom room) {
            List<Integer> range = genMoveRange(room, new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}}, 1);
            //不能走入自家兽穴
            range.removeIf(integer -> isSelfCave((FightingAnimalsRoom) room, integer));
            //不能入河
            range.removeAll(((FightingAnimalsRoom)room).riverIndexList);
            return range;
        }

        @Override
        public List<Integer> getEatRange(MovedChessRoom room) {
            List<Integer> range = genEatRange(room, new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}}, 1);
            //不能入河
            range.removeAll(((FightingAnimalsRoom)room).riverIndexList);
            //不能吃level大于自己的，除非被困住
            List<Integer> removeList = new ArrayList<>();
            for (Integer ran : range) {
                Chess chess = (Chess) room.getChessByIndex(ran);
                if (chess.level > getLevel() && !isSelfTrap((FightingAnimalsRoom)room,ran)){ //等级大于自己且没有被己方陷阱困住时移除
                    removeList.add(ran);
                }
            }
            range.removeAll(removeList);
            return range;
        }
    }

    /**
     * 狼
     */
    private static class Wolf extends Chess {
        public Wolf(int mSide, int pRow, int pCol) {
            super("豹",4, mSide, pRow, pCol);
        }

        @Override
        public String getName() {
            return "🐺";
        }

        @Override
        public List<Integer> getMoveRange(MovedChessRoom room) {
            List<Integer> range = genMoveRange(room, new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}}, 1);
            //不能走入自家兽穴
            range.removeIf(integer -> isSelfCave((FightingAnimalsRoom) room, integer));
            //不能入河
            range.removeAll(((FightingAnimalsRoom)room).riverIndexList);
            return range;
        }

        @Override
        public List<Integer> getEatRange(MovedChessRoom room) {
            List<Integer> range = genEatRange(room, new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}}, 1);
            //不能入河
            range.removeAll(((FightingAnimalsRoom)room).riverIndexList);
            //不能吃level大于自己的，除非被困住
            List<Integer> removeList = new ArrayList<>();
            for (Integer ran : range) {
                Chess chess = (Chess) room.getChessByIndex(ran);
                if (chess.level > getLevel() && !isSelfTrap((FightingAnimalsRoom)room,ran)){ //等级大于自己且没有被己方陷阱困住时移除
                    removeList.add(ran);
                }
            }
            range.removeAll(removeList);
            return range;
        }
    }

    /**
     * 狗
     */
    private static class Dog extends Chess {
        public Dog(int mSide, int pRow, int pCol) {
            super("狗",3, mSide, pRow, pCol);
        }

        @Override
        public String getName() {
            return "🐕";
        }

        @Override
        public List<Integer> getMoveRange(MovedChessRoom room) {
            List<Integer> range = genMoveRange(room, new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}}, 1);
            //不能走入自家兽穴
            range.removeIf(integer -> isSelfCave((FightingAnimalsRoom) room, integer));
            //不能入河
            range.removeAll(((FightingAnimalsRoom)room).riverIndexList);
            return range;
        }

        @Override
        public List<Integer> getEatRange(MovedChessRoom room) {
            List<Integer> range = genEatRange(room, new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}}, 1);
            //不能入河
            range.removeAll(((FightingAnimalsRoom)room).riverIndexList);
            //不能吃level大于自己的，除非被困住
            List<Integer> removeList = new ArrayList<>();
            for (Integer ran : range) {
                Chess chess = (Chess) room.getChessByIndex(ran);
                if (chess.level > getLevel() && !isSelfTrap((FightingAnimalsRoom)room,ran)){ //等级大于自己且没有被己方陷阱困住时移除
                    removeList.add(ran);
                }
            }
            range.removeAll(removeList);
            return range;
        }
    }

    /**
     * 猫
     */
    private static class Cat extends Chess {
        public Cat(int mSide, int pRow, int pCol) {
            super("猫",2, mSide, pRow, pCol);
        }

        @Override
        public String getName() {
            return "🐱";
        }

        @Override
        public List<Integer> getMoveRange(MovedChessRoom room) {
            List<Integer> range = genMoveRange(room, new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}}, 1);
            //不能走入自家兽穴
            range.removeIf(integer -> isSelfCave((FightingAnimalsRoom) room, integer));
            //不能入河
            range.removeAll(((FightingAnimalsRoom)room).riverIndexList);
            return range;
        }

        @Override
        public List<Integer> getEatRange(MovedChessRoom room) {
            List<Integer> range = genEatRange(room, new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}}, 1);
            //不能入河
            range.removeAll(((FightingAnimalsRoom)room).riverIndexList);
            //不能吃level大于自己的，除非被困住
            List<Integer> removeList = new ArrayList<>();
            for (Integer ran : range) {
                Chess chess = (Chess) room.getChessByIndex(ran);
                if (chess.level > getLevel() && !isSelfTrap((FightingAnimalsRoom)room,ran)){ //等级大于自己且没有被己方陷阱困住时移除
                    removeList.add(ran);
                }
            }
            range.removeAll(removeList);
            return range;
        }
    }

    /**
     * 鼠
     */
    private static class Mouse extends Chess {
        public Mouse(int mSide, int pRow, int pCol) {
            super("鼠",1, mSide, pRow, pCol);
        }

        @Override
        public String getName() {
            return "🐀";
        }

        @Override
        public List<Integer> getMoveRange(MovedChessRoom room) {
            List<Integer> range = genMoveRange(room, new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}}, 1);
            //不能走入自家兽穴
            range.removeIf(integer -> isSelfCave((FightingAnimalsRoom) room, integer));
            return range;
        }

        @Override
        public List<Integer> getEatRange(MovedChessRoom room) {
            boolean isOnRiver = ((FightingAnimalsRoom)room).riverIndexList.contains(getIndex(((FightingAnimalsRoom)room)));//判断是否在河中
            List<Integer> range = genEatRange(room, new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}}, 1);
            //入河出河时不能吃子
            if (isOnRiver){
                List<Integer> removeList = new ArrayList<>();
                for (Integer integer : range) {
                    if (!((FightingAnimalsRoom)room).riverIndexList.contains(integer)){
                        removeList.add(integer);
                    }
                }
                range.removeAll(removeList);
            }
            else {
                List<Integer> removeList = new ArrayList<>();
                for (Integer integer : range) {
                    if (((FightingAnimalsRoom)room).riverIndexList.contains(integer)){
                        removeList.add(integer);
                    }
                }
                range.removeAll(removeList);
            }
            //不能吃level大于自己的，除非被困住 能吃大象
            List<Integer> removeList = new ArrayList<>();
            for (Integer ran : range) {
                Chess chess = (Chess) room.getChessByIndex(ran);
                if (chess.level > getLevel() && !isSelfTrap((FightingAnimalsRoom)room,ran)){ //等级大于自己且没有被己方陷阱困住时移除
                    if (!(chess instanceof Elephant)){ //大象能吃不移除
                        removeList.add(ran);
                    }
                }
            }
            range.removeAll(removeList);
            return range;
        }
    }
}
